home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxcode / fmplay11 / adlib.c < prev    next >
C/C++ Source or Header  |  1993-07-26  |  6KB  |  198 lines

  1. /* The original version of this file was written by Kevin A. Lee */
  2. /* (all the bugs are HIS fault. (just kidding)) */
  3.  
  4. #include <conio.h>
  5. #include <time.h>
  6. #include <dos.h>
  7. #include "adlib.h"
  8.  
  9. /**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***\
  10.  * This module MUST be compiled with stack checking OFF in BC 3.0 *
  11. \**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***/
  12.  
  13. /* We wish that THIS would turn stack checking off, but it doesn't work */
  14. #pragma -N-
  15.    
  16. static unsigned char currentB0Contents[9]={0,0,0,0,0,0,0,0,0};
  17. static int percussiveMode=0,currentBDContents=0;
  18. static int opTable[18]={0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21};
  19. static int voiceModulator[11]={0,1,2,6,7,8,12,16,14,17,13};
  20. static int voiceCarrier[9]={3,4,5,9,10,11,15,16,17};
  21.  
  22. /* local function */
  23. void Wait(clock_t wait);
  24.  
  25. void WriteFM(int reg, int value)
  26. {int i;
  27.  outp(ADLIB_FM_ADDRESS, (BYTE)reg);              /* set up the register  */
  28.  for (i = 0; i < 6; i++) inp(ADLIB_FM_ADDRESS);  /* wait 12 cycles       */
  29.  outp(ADLIB_FM_DATA, (BYTE)value);               /* write out the value  */
  30.  for (i = 0; i < 35; i++) inp(ADLIB_FM_ADDRESS); /* wait 84 cycles       */
  31. }
  32.  
  33. int ReadFM(void)
  34. {return (inp(ADLIB_FM_ADDRESS));
  35. }
  36.  
  37. int AdlibExists(void)
  38. {int stat1, stat2;
  39.  WriteFM(0x04, 0x60);            /* reset both timers        */
  40.  WriteFM(0x04, 0x80);            /* enable timer interrupts  */
  41.  stat1 = ReadFM();               /* read status register     */
  42.  WriteFM(0x02, 0xFF);
  43.  WriteFM(0x04, 0x21);            /* start timer 1            */
  44.  Wait(80);                       /* could do something useful*/
  45.  stat2 = ReadFM();               /* read status register     */
  46.  WriteFM(0x04, 0x60);            /* reset both timers        */
  47.  WriteFM(0x04, 0x80);            /* enable timer interrupts  */
  48.  
  49.  if (((stat1 & 0xE0) == 0x00) && ((stat2 & 0xE0) == 0xC0)) return (1);
  50.  return (0);
  51. }
  52.  
  53. void FMReset(int percusiveMode)
  54. {
  55.  int i;
  56.  /* zero all registers */
  57.  for (i = MIN_REGISTER; i < MAX_REGISTER+1; i++) WriteFM(i, 0);
  58.  /* allow FM chips to control the waveform of each operator */
  59.  WriteFM(0x01, 0x20);
  60.  FMSetPercusiveMode(percusiveMode);
  61. }
  62.  
  63. void FMSetPercusiveMode(int state)
  64. {if (state)
  65.     {WriteFM(0xBD, 0x20);
  66.      currentBDContents=0x20;
  67.      percussiveMode=1;
  68.      voiceModulator[7]=16;
  69.      voiceModulator[8]=14;
  70.      /* we have to set the freq of voice 7 & 8 for the white noise gen.*/
  71.      /* these frequency choices could certainly be better */
  72.      WriteFM(0xa7, 1844 & 0xff);
  73.      WriteFM(0xb7, 1844 >> 8);
  74.      WriteFM(0xa8, 3764 & 0xff);
  75.      WriteFM(0xb8, 3764 >> 8);
  76.     }
  77. else
  78.    {WriteFM(0xBD, 0);
  79.     percussiveMode=0;
  80.     currentBDContents=0;
  81.     voiceModulator[7]=13;
  82.     voiceModulator[8]=14;
  83.    }
  84. }
  85.  
  86. void FMKeyOff(int voice)
  87. {int regNum;
  88.  /* turn voice off */
  89.  if (percussiveMode && voice>5)
  90.     {currentBDContents&=(0xFF-(16 >> (voice-6)));
  91.      WriteFM(0xBD,currentBDContents);
  92.     }
  93.  else
  94.     {regNum = 0xB0 + voice;
  95.      WriteFM(regNum, currentB0Contents[voice] & 0xdf);
  96.      /* must preserve frequency for release stage of envelope */
  97.     }
  98. }
  99.  
  100. void FMKeyOn(int voice, int freq)
  101. {
  102.  int regNum, tmp;
  103.  if (percussiveMode && voice>5)
  104.     {currentBDContents|=16 >> (voice-6);
  105.      if (voice==6 || voice==8) /* bass and tom-tom are pitched */
  106.     {regNum = 0xA0 + voice;
  107.      WriteFM(regNum, freq & 0xff);
  108.      regNum = 0xB0 + voice;
  109.      tmp = (freq >> 8);
  110.      WriteFM(regNum, tmp);
  111.     }
  112.      WriteFM(0xBD,currentBDContents);
  113.     }
  114.  else
  115.     {regNum = 0xA0 + voice;
  116.      WriteFM(regNum, freq & 0xff);
  117.      regNum = 0xB0 + voice;
  118.      tmp = (freq >> 8) | 0x20;
  119.      WriteFM(regNum, tmp);
  120.      currentB0Contents[voice]=tmp;
  121.     }
  122. }
  123.  
  124. void FMVoiceVolume(int voice, int vol)
  125. {int regNum;
  126.  regNum = 0x40+opTable[voiceModulator[voice]];
  127.  WriteFM(regNum, vol); /* must preserve KSL (but don't yet!) */
  128. }
  129.  
  130. void FMSetVoice(int voiceNum, FMInstrument *ins)
  131. {int modO,carO,i;
  132.  if (voiceNum<7 || !percussiveMode) /* note: base drum included */
  133.     {modO=opTable[voiceModulator[voiceNum]];
  134.      carO=opTable[voiceCarrier[voiceNum]];
  135.      WriteFM(0x20+modO,
  136.          (ins->MOD_amplitudeVibrato << 7) +
  137.          (ins->MOD_frequencyVibrato << 6) +
  138.          (ins->MOD_ss << 5)               +
  139.          (ins->MOD_envelopeScaling << 4)  +
  140.          (ins->MOD_fMult));
  141.      WriteFM(0x40+modO,
  142.          (ins->MOD_KSL << 6) +
  143.          (ins->MOD_outputLevel));
  144.      WriteFM(0x60+modO,
  145.          (ins->MOD_attack << 4) + (ins->MOD_decay));
  146.      WriteFM(0x80+modO,
  147.          (ins->MOD_sustain << 4) + (ins->MOD_release));
  148.      WriteFM(0xe0+modO,ins->MOD_waveForm);
  149.      
  150.      WriteFM(0x20+carO,
  151.          (ins->CAR_amplitudeVibrato << 7) +
  152.          (ins->CAR_frequencyVibrato << 6) +
  153.          (ins->CAR_ss << 5)               +
  154.          (ins->CAR_envelopeScaling << 4)  +
  155.          (ins->CAR_fMult));
  156.      WriteFM(0x40+carO,
  157.          (ins->CAR_KSL << 6) +
  158.          (ins->CAR_outputLevel));
  159.      WriteFM(0x60+carO,
  160.          (ins->CAR_attack << 4) + (ins->CAR_decay));
  161.      WriteFM(0x80+carO,
  162.          (ins->CAR_sustain << 4) + (ins->CAR_release));
  163.      WriteFM(0xe0+carO,ins->CAR_waveForm);
  164.      if (ins->FM) /* is the adlib documentation fucked or what? */
  165.     i=0;
  166.      else
  167.     i=1;
  168.      WriteFM(0xC0+voiceNum,(ins->feedBack << 1) + i);
  169.     }
  170.  else
  171.     {modO=opTable[voiceModulator[voiceNum]];
  172.      WriteFM(0x20+modO,
  173.          (ins->MOD_amplitudeVibrato << 7) +
  174.          (ins->MOD_frequencyVibrato << 6) +
  175.          (ins->MOD_ss << 5)               +
  176.          (ins->MOD_envelopeScaling << 4)  +
  177.          (ins->MOD_fMult));
  178.      WriteFM(0x40+modO,
  179.          (ins->MOD_KSL << 6) +
  180.          (ins->MOD_outputLevel));
  181.      WriteFM(0x60+modO,
  182.          (ins->MOD_attack << 4) + (ins->MOD_decay));
  183.      WriteFM(0x80+modO,
  184.          (ins->MOD_sustain << 4) + (ins->MOD_release));
  185.      WriteFM(0xe0+modO,ins->MOD_waveForm);
  186.     }
  187. }
  188.  
  189. void Wait(clock_t wait)
  190. {clock_t goal;
  191.  if (!wait) return;
  192.  goal = wait + clock();
  193.  while ((goal > clock())) ;
  194. }
  195.  
  196.  
  197.  
  198.